#include "boardwidget.h"
#include "ui_boardwidget.h"

#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QPoint>
#include <QMouseEvent>
#include <QSize>
#include <QLabel>
#include <QDebug>


//棋盘的起始位置：
const QPoint BoardWidget::ROW_NUM_START(45, 30);
const QPoint BoardWidget::COLUMN_NUM_START(20, 55);

//size初始化
const QSize BoardWidget::WIDGET_SIZE(800, 800);
const QSize BoardWidget::CELL_SIZE(50, 50);

const QPoint BoardWidget::START_POS(50, 50);

BoardWidget::BoardWidget(QWidget *parent) : QWidget(parent),ui(new Ui::BoardWidget),trackPos(28, 28)
{
    ui->setupUi(this);
    setFixedSize(WIDGET_SIZE);     // 设置窗口为固定大小
    setMouseTracking(false);
    endGame = true;
    ui->label->move(-100,-100);
    qDebug()<<"from board:" << QThread::currentThreadId();
    ai = new AI();
    thread = new QThread();
    ai->moveToThread(thread);
    connect(ai, SIGNAL(sendPredict(int, int)), this, SLOT(setPredict(int, int)));
    connect(this, SIGNAL(aiDrop(int*, bool, int, int)), ai, SLOT(setRoot(int*, bool, int, int)));
    thread->start();
}

BoardWidget::~BoardWidget()
{
    delete ui;
}

void BoardWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

    //首先先设置画笔
    QPen pen;
    pen.setWidth(3);
    pen.setStyle(Qt::SolidLine);

    //设置标记画刷
    QPen pen_tip;
    pen_tip.setColor(Qt::blue);
    pen_tip.setStyle(Qt::DashLine);

    //设置画刷
    QBrush brush;
    brush.setColor(QColor(186,140,64));
    brush.setStyle(Qt::SolidPattern);

    //填充背景颜色
    painter.fillRect(this->rect(), Qt::gray);

    //给予画家画笔
    painter.setPen(pen);
    painter.setBrush(brush);


    //    QRect recf = QRect(0,0,50,50);
    //    painter.drawRect(recf);

    // 设置字体
    QFont font;
    font.setPointSize(10);
    font.setBold(true);
    painter.setFont(font);

    //开始绘图,画出整个棋盘
    int x = START_POS.x();
    int y = START_POS.y();
    int width = 14*CELL_SIZE.width();
    int height = 14*CELL_SIZE.height();
    painter.drawRect(x,y,width,height);
    for (int i=0;i<=height;i=i+CELL_SIZE.height())
    {
        painter.drawLine(x,y+i,x+width,y+i);
    }

    for (int i=0;i<=width;i=i+CELL_SIZE.width())
    {
        painter.drawLine(x+i,y,x+i,y+height);
    }


    //画出列方向的数字
    width = CELL_SIZE.width();
    height = CELL_SIZE.height();
    for(int i=0; i<BOARD_HEIGHT; i++)
    {
        painter.drawText(COLUMN_NUM_START + QPoint(0,i*height), QString::number(i+1));
    }

    //画出行方向的数字
    for(int j=0; j<BOARD_WIDTH; j++)
    {
        painter.drawText(ROW_NUM_START + QPoint(j*width,0), QString::number(j+1));
    }


    //画出棋盘上的五个小圆点
    brush.setColor(Qt::black);
    painter.setBrush(brush);
    painter.drawEllipse(QPoint(width*8,height*8),5,5);
    painter.drawEllipse(QPoint(width*4,height*4),5,5);
    painter.drawEllipse(QPoint(width*12,height*4),5,5);
    painter.drawEllipse(QPoint(width*4,height*12),5,5);
    painter.drawEllipse(QPoint(width*12,height*12),5,5);

    //画出鼠标位置

    //谁下棋画谁的棋子
    painter.setPen(Qt::NoPen);
    if(!endGame)
    {
        QColor color;
        if(next_player == BLACK_PLAYER)
            color = Qt::black;
        else
            color = Qt::white;
        painter.setBrush(QBrush(color));
        int x = trackPos.x()-8;
        int y = trackPos.y()-8;
        painter.drawEllipse(x,y,width-4,height-4);


        /*
         * 对于当前鼠标的位置用红框提醒出来
        pen.setColor(Qt::red);
        pen.setStyle(Qt::DashLine);
        painter.setPen(pen);
        painter.setBrush(Qt::NoBrush);
        painter.drawRect((trackPos+QPoint(0,0)).x(),(trackPos+QPoint(0,0)).y(),34,34);
        */

    }


    // 绘制棋子
    // 查看棋盘的状态
    for(int i=0; i<BOARD_HEIGHT; i++)
    {
        for(int j=0; j<BOARD_WIDTH; j++)
        {
            QColor chess_color;

            if(board[i][j] == WHITE_PIECE)
            {
                chess_color = Qt::white;
                painter.setBrush(QBrush(chess_color));
                painter.drawEllipse(START_POS.y() + j*CELL_SIZE.height() - CELL_SIZE.height()/2,
                                    START_POS.x() + i*CELL_SIZE.width() - CELL_SIZE.width()/2,
                                    CELL_SIZE.width()-4,
                                    CELL_SIZE.height()-4);
                eraser_x = START_POS.x() + j*CELL_SIZE.width() - CELL_SIZE.width()/2+10;
                eraser_y = START_POS.y() + i*CELL_SIZE.height() - CELL_SIZE.height()/2;
                ui->label->move(eraser_x,eraser_y);
                update();
            }
            else
                if(board[i][j] == BLACK_PIECE)
            {

                chess_color = Qt::black;
                painter.setBrush(QBrush(chess_color));
                painter.drawEllipse(START_POS.y() + j*CELL_SIZE.height() - CELL_SIZE.height()/2,
                                    START_POS.x() + i*CELL_SIZE.width() - CELL_SIZE.width()/2,
                                    CELL_SIZE.width()-4,
                                    CELL_SIZE.height()-4);
                eraser_x = START_POS.x() + j*CELL_SIZE.width() - CELL_SIZE.width()/2+10;
                eraser_y = START_POS.y() + i*CELL_SIZE.height() - CELL_SIZE.height()/2;
                ui->label->move(eraser_x,eraser_y);
                update();

            }
            else
            {
                painter.setPen(Qt::NoPen);
            }
        }
    }

}


void BoardWidget::mouseMoveEvent(QMouseEvent *event)    // 鼠标事件
{
    QPoint pos = event->pos() - START_POS;    // 相对于棋盘起始位置的坐标
    QPoint temp_point = pos + QPoint(CELL_SIZE.width()/2, CELL_SIZE.height()/2);   // 坐标
    int x = temp_point.x();
    int y = temp_point.y();

    if(x <= 0 || y <= 0 || x >= BOARD_WIDTH*CELL_SIZE.width() || y >= BOARD_HEIGHT*CELL_SIZE.height())
    {
        return;
    }
    int offset_x = x % CELL_SIZE.width();    // 这个坐标表示不够一个cell_size的坐标的大小
    int offset_y = y % CELL_SIZE.height();

    // 绘制的图标的位置，中心的为十字交叉的位置

    QPoint tip_position = QPoint(x-offset_x, y-offset_y)+START_POS-
        QPoint(CELL_SIZE.width()/2, CELL_SIZE.height()/2)+
        QPoint(8, 8);
    setTrackPos(tip_position);

}


void BoardWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if(!endGame)      // 游戏未结束
    {
        QPoint pos = event->pos() - START_POS;
        int x = pos.x();
        int y = pos.y();
        int x_pos = x / CELL_SIZE.width();         // 整数，确定第几个格子
        int y_pos = y / CELL_SIZE.height();
        int x_offset = x % CELL_SIZE.width();     // 余数，计算是否需要偏移
        int y_offset = y % CELL_SIZE.height();
        if(x_offset > CELL_SIZE.width()/2)
        {
            x_pos++;
        }
        if(y_offset > CELL_SIZE.height()/2)
        {
            y_pos++;
        }
        dropPiece(y_pos,x_pos);

        if (!endGame)
        {
            int* map = new int[225];
            for (int i = 0; i < 15; i++)
            {

                for (int j = 0; j < 15; j++)
                {
                    map[i * 15 + j] = board[i][j];
                    //cout << map[i * 15 + j];
                    //if (j == 14)
                        //cout << endl;
                    //else
                    //    cout << " ";
                }
            }

            emit aiDrop(map, next_player, y_pos, x_pos);
        }
    }
}

void BoardWidget::initBoard()
{
    // 对棋盘进行初始化
    for(int i=0; i<BOARD_WIDTH; i++)
    {
        for(int j=0; j<BOARD_HEIGHT; j++)
        {
            board[i][j] = NO_PIECE;
        }
    }

    setMouseTracking(true);        // 开启MouseTracking
    endGame = false;

    // 黑棋先落子
    WHITE_PALYER = false;
    BLACK_PLAYER = true;
    next_player = BLACK_PLAYER;

    update();

}


void BoardWidget::setTrackPos(QPoint point)
{
    trackPos = point;
    update();   // update的作用是更新窗口部件
}


void BoardWidget::dropPiece(int x, int y)
{
    if(x>=0 && x<=BOARD_HEIGHT && y>=0 && y<=BOARD_WIDTH && board[x][y]==NO_PIECE)
    {
        if(next_player == WHITE_PALYER)
        {
            board[x][y] = WHITE_PIECE;      // 当前位置是白棋
        }
        else
        {
            board[x][y] = BLACK_PIECE;      // 当前位置是黑棋
        }
        // 判断输赢
        checkWinner();

        // 切换落子的玩家
        next_player = !next_player;
        emit signalPlayerChanged(next_player);

        update();     // 更新窗口组件

    }


}

//由于坐标变换 所以水平《-》垂直， 左对角《=》右对角
bool BoardWidget::isHFivePiece(int x, int y)
{
    // 判断水平方向
    int piece = board[x][y];     // 当前棋子的值
    for(int i=1; i<5; i++)
    {
        if(x+i>BOARD_WIDTH || board[x+i][y]!=piece)
        {
            return false;
        }
    }
    return true;
}


bool BoardWidget::isVFivePiece(int x, int y)
{
    // 判断垂直方向
    int piece = board[x][y];
    for(int i=1; i<5; i++)
    {
        if(y+i>BOARD_HEIGHT || board[x][y+i]!=piece)
        {
            return false;
        }
    }
    return true;
}

bool BoardWidget::isLeftSlash(int x, int y)
{
    // 沿着左对角线
    int piece = board[x][y];
    for(int i=1; i<5; i++)
    {
        if(x+i>BOARD_WIDTH || y+i>BOARD_HEIGHT || board[x+i][y+i]!=piece)
        {
            return false;
        }
    }
    return true;
}

bool BoardWidget::isRightSlash(int x, int y)
{
    // 沿着右对角线
    int piece = board[x][y];
    for(int i=1; i<5; i++)
    {
        if(x-i<0 || y+i>BOARD_HEIGHT || board[x-i][y+i]!=piece)
        {
            return false;
        }
    }
    return true;
}

bool BoardWidget::isFivePiece(int x, int y)
{
    // 是否赢棋
    return isHFivePiece(x, y) || isVFivePiece(x, y) || isLeftSlash(x, y) || isRightSlash(x, y);
}


void BoardWidget::checkWinner()
{
    bool fullPieces = true;     // 和棋
    for(int i=0; i<BOARD_HEIGHT; i++)
    {
        for(int j=0; j<BOARD_WIDTH; j++)
        {
            if(board[i][j]==NO_PIECE)    // 如果棋盘不是满的，就不是和棋
            {
                fullPieces = false;
            }
            if(board[i][j]!=NO_PIECE && isFivePiece(i, j))
            {
                int winner;
                if(board[i][j]==WHITE_PIECE)
                {
                    winner = WHITE_PIECE;
                }
                else
                {
                    winner = BLACK_PIECE;
                }
                emit signalGameOver(winner);
                endGame = true;
            }
        }
    }
    if(fullPieces)
    {
        emit signalGameOver(3);
    }
}

void BoardWidget::slotTimeOut()
{
    endGame = true;
}

void BoardWidget::setPredict(int x, int y)
{
    cout << "predict:" << x << " " << y << endl;
    dropPiece(x, y);
}
